{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Quantum Phase Estimation Examples\n",
    "\n",
    "This notebook gives some examples of how to use Qubiter to write and simulate a quantum\n",
    "circuit that does quantum phase estimation (qPE).\n",
    "\n",
    "Even though qPE was invented by Kitaev, it can be understood \n",
    "(See IBM Quantum Experience Tutorial for the details) as\n",
    "a quantum computer version of a much earlier model, namely, \n",
    "the von Neumann Pointer-System model for a quantum\n",
    "mechanical measurement.\n",
    "\n",
    "\n",
    "In the case of quantum computers, \n",
    "the Pointer in von Neumann's model is represented by several \"pointer qubits\"\n",
    "and the System by several \"system qubits\".\n",
    "The matrix U whose eigenvalues we wish to find\n",
    "acts on the System qubits.\n",
    "\n",
    "In Qubiter, we call the \"pointer qubits\" the \"probes\", and the qbits that U acts on the \"atom qbits\". We call U the \"atom matrix\".\n",
    "$\\newcommand{\\bra}[1]{\\left\\langle{#1}\\right|}$\n",
    "$\\newcommand{\\ket}[1]{\\left|{#1}\\right\\rangle}$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First change your working directory to the qubiter directory in your computer, and add its path to the path environment variable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/home/rrtucci/PycharmProjects/qubiter/qubiter/jupyter_notebooks\n",
      "/home/rrtucci/PycharmProjects/qubiter\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "print(os.getcwd())\n",
    "os.chdir('../../')\n",
    "print(os.getcwd())\n",
    "sys.path.insert(0,os.getcwd())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loaded OneQubitGate, WITHOUT autograd.numpy\n"
     ]
    }
   ],
   "source": [
    "from qubiter.SEO_writer import *\n",
    "from qubiter.SEO_simulator import *\n",
    "from qubiter.StateVec import *\n",
    "from qubiter.adv_applications.PhaseEstSEO_writer import PhaseEstSEO_writer\n",
    "from qubiter.adv_applications.PhaseEstSEO_writer import AtomWriter\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example a: \n",
    "In this example, 2 qbits are used\n",
    "\n",
    "probe qubits = {0}, \n",
    "\n",
    "atom qubits = {1}\n",
    "\n",
    "The atom matrix is the X Pauli matrix, $U = \\sigma_X$\n",
    "\n",
    "Eigenvectors of U are \n",
    "\n",
    "$H\\ket{0} = \\frac{1}{\\sqrt{2}}(\\ket{0} + \\ket{1})$ for +1\n",
    "\n",
    "$H\\ket{1} = \\frac{1}{\\sqrt{2}}(\\ket{0} - \\ket{1})$ for -1\n",
    "\n",
    "where $H = \\frac{1}{\\sqrt{2}}\\left[ \\begin{array}{cc} 1 & 1\\\\ 1 & -1 \\end{array}\\right ]$\n",
    "is the Hadamard matrix"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Open a writer, tell it where to write to.\n",
    "We will use zero bit last (ZL) convention."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_qbits = 2\n",
    "emb = CktEmbedder(num_qbits, num_qbits)\n",
    "file_prefix = 'ph_est_nb_a'\n",
    "wr = SEO_writer(file_prefix, emb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next write the whole circuit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "wr.write_one_qbit_gate(1, OneQubitGate.had2)\n",
    "wr.write_one_qbit_gate(0, OneQubitGate.had2)\n",
    "\n",
    "control_pos = 0\n",
    "target_pos = 1\n",
    "trols = Controls.new_single_trol(num_qbits, control_pos, kind=True)\n",
    "wr.write_controlled_one_qbit_gate(\n",
    "    target_pos, trols, OneQubitGate.sigx)\n",
    "\n",
    "wr.write_one_qbit_gate(0, OneQubitGate.had2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Close English and Picture files"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "wr.close_files()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Look in files\n",
    "\n",
    "* <a href=\"../io_folder/ph_est_nb_a_2_eng.txt\">../io_folder/ph_est_nb_a_2_eng.txt</a>\n",
    "* <a href=\"../io_folder/ph_est_nb_a_2_ZLpic.txt\">../io_folder/ph_est_nb_a_2_ZLpic.txt</a>\n",
    "\n",
    "to see the quantum circuit that was generated"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Print the Picture file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>H   |</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>|   H</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>X---@</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>|   H</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "wr.print_pic_file(jup=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Specify initial state vector for simulation. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "init_st_vec = StateVec.get_standard_basis_st_vec([0, 0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Open a simulator. This automatically\n",
    "multiplies quantum circuit in given file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "sim = SEO_simulator(file_prefix, num_qbits, init_st_vec)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Print description of final state vector"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*********branch= pure\n",
      "state vector:\n",
      "ZL convention (Zero bit Last in state tuple)\n",
      "(00)ZL ( 0.707107 + 0.000000j)\t prob=0.500000\n",
      "(10)ZL ( 0.707107 + 0.000000j)\t prob=0.500000\n",
      "total probability of state vector (=one if no measurements)= 1.000000\n",
      "dictionary with key=qubit, value=(Prob(0), Prob(1))\n",
      "{0: (1.0, 0.0), 1: (0.5, 0.5)}\n"
     ]
    }
   ],
   "source": [
    "StateVec.describe_st_vec_dict(sim.cur_st_vec_dict, \n",
    "        print_st_vec=True, do_pp=True, omit_zero_amps=True, show_pp_probs=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example b:\n",
    "In this example, num_qbits are used\n",
    "\n",
    "probe qubits = {0, 1, 2, ..., num_qbits-2}\n",
    "\n",
    "atom qubits = {num_qbits-1}\n",
    "\n",
    "The atom matrix is a Z axis rotation, $U = e^{i*rads*\\sigma_Z}$, for some \n",
    "Real number $rads$\n",
    "\n",
    "Eigenvectors of U are same as those for $\\sigma_Z$, $\\ket{0}$ and $\\ket{1}$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "An object of the AtomWriter2 class will be called by the writer of the full qPE circuit \n",
    "to write the powers of the atom matrix."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "class AtomWriter2(AtomWriter):\n",
    "    \n",
    "    def __init__(self, do_write, rads, **kwargs):\n",
    "        self.rads = rads\n",
    "        AtomWriter.__init__(self, do_write, **kwargs)\n",
    "        \n",
    "    def write_pow(self, power):\n",
    "        z_axis = 3\n",
    "        self.write_one_qbit_gate(0, OneQubitGate.rot_ax, [power*self.rads, z_axis])\n",
    "        \n",
    "    def write_pow_hermitian(self, power):\n",
    "        z_axis = 3\n",
    "        self.write_one_qbit_gate(0, OneQubitGate.rot_ax, [-power*self.rads, z_axis])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------Number of bits= 2\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>|   H</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>Rz--@</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>|   H</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*********branch= pure\n",
      "state vector:\n",
      "ZL convention (Zero bit Last in state tuple)\n",
      "(00)ZL ( 0.961940 + 0.191342j)\t prob=0.961940\n",
      "(01)ZL ( 0.038060 - 0.191342j)\t prob=0.038060\n",
      "total probability of state vector (=one if no measurements)= 1.000000\n",
      "dictionary with key=qubit, value=(Prob(0), Prob(1))\n",
      "{0: (0.96194, 0.03806), 1: (1.0, 0.0)}\n",
      "spike_bit prediction= -3.0\n",
      "-----------------Number of bits= 3\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>|   |   H</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>|   H   |</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>Rz--+---@</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>Rz--@   |</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>|   H   |</pre></td></tr><td style='border-right:1px solid red;'>6</td><td style='text-align:left;'><pre>|   @P--@</pre></td></tr><td style='border-right:1px solid red;'>7</td><td style='text-align:left;'><pre>|   |   H</pre></td></tr><td style='border-right:1px solid red;'>8</td><td style='text-align:left;'><pre>|   <---></pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*********branch= pure\n",
      "state vector:\n",
      "ZL convention (Zero bit Last in state tuple)\n",
      "(000)ZL ( 0.753417 + 0.503417j)\t prob=0.821067\n",
      "(010)ZL ( 0.100136 - 0.149864j)\t prob=0.032486\n",
      "(001)ZL (-0.062076 - 0.312076j)\t prob=0.101245\n",
      "(011)ZL ( 0.208522 - 0.041478j)\t prob=0.045202\n",
      "total probability of state vector (=one if no measurements)= 1.000000\n",
      "dictionary with key=qubit, value=(Prob(0), Prob(1))\n",
      "{0: (0.853553, 0.146447), 1: (0.922312, 0.077688), 2: (1.0, 0.0)}\n",
      "spike_bit prediction= -2.0\n",
      "-----------------Number of bits= 4\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>|   |   |   H</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>|   |   H   |</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>|   H   |   |</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>Rz--+---+---@</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>Rz--+---@   |</pre></td></tr><td style='border-right:1px solid red;'>6</td><td style='text-align:left;'><pre>Rz--@   |   |</pre></td></tr><td style='border-right:1px solid red;'>7</td><td style='text-align:left;'><pre>|   H   |   |</pre></td></tr><td style='border-right:1px solid red;'>8</td><td style='text-align:left;'><pre>|   @P--@   |</pre></td></tr><td style='border-right:1px solid red;'>9</td><td style='text-align:left;'><pre>|   |   H   |</pre></td></tr><td style='border-right:1px solid red;'>10</td><td style='text-align:left;'><pre>|   @P--+---@</pre></td></tr><td style='border-right:1px solid red;'>11</td><td style='text-align:left;'><pre>|   |   @P--@</pre></td></tr><td style='border-right:1px solid red;'>12</td><td style='text-align:left;'><pre>|   |   |   H</pre></td></tr><td style='border-right:1px solid red;'>13</td><td style='text-align:left;'><pre>|   |   <---></pre></td></tr><td style='border-right:1px solid red;'>14</td><td style='text-align:left;'><pre>|   <---+---></pre></td></tr><td style='border-right:1px solid red;'>15</td><td style='text-align:left;'><pre>|   <--->   |</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*********branch= pure\n",
      "state vector:\n",
      "ZL convention (Zero bit Last in state tuple)\n",
      "(0000)ZL ( 0.125000 + 0.628417j)\t prob=0.410533\n",
      "(0100)ZL ( 0.125000 - 0.024864j)\t prob=0.016243\n",
      "(0010)ZL ( 0.125000 - 0.187076j)\t prob=0.050622\n",
      "(0110)ZL ( 0.125000 + 0.083522j)\t prob=0.022601\n",
      "(0001)ZL ( 0.125000 - 0.628417j)\t prob=0.410533\n",
      "(0101)ZL ( 0.125000 + 0.024864j)\t prob=0.016243\n",
      "(0011)ZL ( 0.125000 - 0.083522j)\t prob=0.022601\n",
      "(0111)ZL ( 0.125000 + 0.187076j)\t prob=0.050622\n",
      "total probability of state vector (=one if no measurements)= 1.000000\n",
      "dictionary with key=qubit, value=(Prob(0), Prob(1))\n",
      "{0: (0.5, 0.5), 1: (0.853553, 0.146447), 2: (0.89429, 0.10571), 3: (1.0, 0.0)}\n",
      "spike_bit prediction= -1.0\n",
      "-----------------Number of bits= 5\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>|   |   |   |   H</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>|   |   |   H   |</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>|   |   H   |   |</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>|   H   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>Rz--+---+---+---@</pre></td></tr><td style='border-right:1px solid red;'>6</td><td style='text-align:left;'><pre>Rz--+---+---@   |</pre></td></tr><td style='border-right:1px solid red;'>7</td><td style='text-align:left;'><pre>Rz--+---@   |   |</pre></td></tr><td style='border-right:1px solid red;'>8</td><td style='text-align:left;'><pre>Rz--@   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>9</td><td style='text-align:left;'><pre>|   H   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>10</td><td style='text-align:left;'><pre>|   @P--@   |   |</pre></td></tr><td style='border-right:1px solid red;'>11</td><td style='text-align:left;'><pre>|   |   H   |   |</pre></td></tr><td style='border-right:1px solid red;'>12</td><td style='text-align:left;'><pre>|   @P--+---@   |</pre></td></tr><td style='border-right:1px solid red;'>13</td><td style='text-align:left;'><pre>|   |   @P--@   |</pre></td></tr><td style='border-right:1px solid red;'>14</td><td style='text-align:left;'><pre>|   |   |   H   |</pre></td></tr><td style='border-right:1px solid red;'>15</td><td style='text-align:left;'><pre>|   @P--+---+---@</pre></td></tr><td style='border-right:1px solid red;'>16</td><td style='text-align:left;'><pre>|   |   @P--+---@</pre></td></tr><td style='border-right:1px solid red;'>17</td><td style='text-align:left;'><pre>|   |   |   @P--@</pre></td></tr><td style='border-right:1px solid red;'>18</td><td style='text-align:left;'><pre>|   |   |   |   H</pre></td></tr><td style='border-right:1px solid red;'>19</td><td style='text-align:left;'><pre>|   |   |   <---></pre></td></tr><td style='border-right:1px solid red;'>20</td><td style='text-align:left;'><pre>|   |   <---+---></pre></td></tr><td style='border-right:1px solid red;'>21</td><td style='text-align:left;'><pre>|   |   <--->   |</pre></td></tr><td style='border-right:1px solid red;'>22</td><td style='text-align:left;'><pre>|   <---+---+---></pre></td></tr><td style='border-right:1px solid red;'>23</td><td style='text-align:left;'><pre>|   <---+--->   |</pre></td></tr><td style='border-right:1px solid red;'>24</td><td style='text-align:left;'><pre>|   <--->   |   |</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*********branch= pure\n",
      "state vector:\n",
      "ZL convention (Zero bit Last in state tuple)\n",
      "(00001)ZL ( 1.000000 - 0.000000j)\t prob=1.000000\n",
      "total probability of state vector (=one if no measurements)= 1.000000\n",
      "dictionary with key=qubit, value=(Prob(0), Prob(1))\n",
      "{0: (0.0, 1.0), 1: (1.0, 0.0), 2: (1.0, 0.0), 3: (1.0, 0.0), 4: (1.0, 0.0)}\n",
      "spike_bit prediction= 0.0\n",
      "-----------------Number of bits= 6\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>|   |   |   |   |   H</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>|   |   |   |   H   |</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>|   |   |   H   |   |</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>|   |   H   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>|   H   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>6</td><td style='text-align:left;'><pre>Rz--+---+---+---+---@</pre></td></tr><td style='border-right:1px solid red;'>7</td><td style='text-align:left;'><pre>Rz--+---+---+---@   |</pre></td></tr><td style='border-right:1px solid red;'>8</td><td style='text-align:left;'><pre>Rz--+---+---@   |   |</pre></td></tr><td style='border-right:1px solid red;'>9</td><td style='text-align:left;'><pre>Rz--+---@   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>10</td><td style='text-align:left;'><pre>Rz--@   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>11</td><td style='text-align:left;'><pre>|   H   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>12</td><td style='text-align:left;'><pre>|   @P--@   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>13</td><td style='text-align:left;'><pre>|   |   H   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>14</td><td style='text-align:left;'><pre>|   @P--+---@   |   |</pre></td></tr><td style='border-right:1px solid red;'>15</td><td style='text-align:left;'><pre>|   |   @P--@   |   |</pre></td></tr><td style='border-right:1px solid red;'>16</td><td style='text-align:left;'><pre>|   |   |   H   |   |</pre></td></tr><td style='border-right:1px solid red;'>17</td><td style='text-align:left;'><pre>|   @P--+---+---@   |</pre></td></tr><td style='border-right:1px solid red;'>18</td><td style='text-align:left;'><pre>|   |   @P--+---@   |</pre></td></tr><td style='border-right:1px solid red;'>19</td><td style='text-align:left;'><pre>|   |   |   @P--@   |</pre></td></tr><td style='border-right:1px solid red;'>20</td><td style='text-align:left;'><pre>|   |   |   |   H   |</pre></td></tr><td style='border-right:1px solid red;'>21</td><td style='text-align:left;'><pre>|   @P--+---+---+---@</pre></td></tr><td style='border-right:1px solid red;'>22</td><td style='text-align:left;'><pre>|   |   @P--+---+---@</pre></td></tr><td style='border-right:1px solid red;'>23</td><td style='text-align:left;'><pre>|   |   |   @P--+---@</pre></td></tr><td style='border-right:1px solid red;'>24</td><td style='text-align:left;'><pre>|   |   |   |   @P--@</pre></td></tr><td style='border-right:1px solid red;'>25</td><td style='text-align:left;'><pre>|   |   |   |   |   H</pre></td></tr><td style='border-right:1px solid red;'>26</td><td style='text-align:left;'><pre>|   |   |   |   <---></pre></td></tr><td style='border-right:1px solid red;'>27</td><td style='text-align:left;'><pre>|   |   |   <---+---></pre></td></tr><td style='border-right:1px solid red;'>28</td><td style='text-align:left;'><pre>|   |   |   <--->   |</pre></td></tr><td style='border-right:1px solid red;'>29</td><td style='text-align:left;'><pre>|   |   <---+---+---></pre></td></tr><td style='border-right:1px solid red;'>30</td><td style='text-align:left;'><pre>|   |   <---+--->   |</pre></td></tr><td style='border-right:1px solid red;'>31</td><td style='text-align:left;'><pre>|   |   <--->   |   |</pre></td></tr><td style='border-right:1px solid red;'>32</td><td style='text-align:left;'><pre>|   <---+---+---+---></pre></td></tr><td style='border-right:1px solid red;'>33</td><td style='text-align:left;'><pre>|   <---+---+--->   |</pre></td></tr><td style='border-right:1px solid red;'>34</td><td style='text-align:left;'><pre>|   <---+--->   |   |</pre></td></tr><td style='border-right:1px solid red;'>35</td><td style='text-align:left;'><pre>|   <--->   |   |   |</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*********branch= pure\n",
      "state vector:\n",
      "ZL convention (Zero bit Last in state tuple)\n",
      "(000010)ZL ( 1.000000 - 0.000000j)\t prob=1.000000\n",
      "total probability of state vector (=one if no measurements)= 1.000000\n",
      "dictionary with key=qubit, value=(Prob(0), Prob(1))\n",
      "{0: (1.0, 0.0),\n",
      " 1: (0.0, 1.0),\n",
      " 2: (1.0, 0.0),\n",
      " 3: (1.0, 0.0),\n",
      " 4: (1.0, 0.0),\n",
      " 5: (1.0, 0.0)}\n",
      "spike_bit prediction= 1.0\n",
      "-----------------Number of bits= 7\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>|   |   |   |   |   |   H</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>|   |   |   |   |   H   |</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>|   |   |   |   H   |   |</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>|   |   |   H   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>|   |   H   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>6</td><td style='text-align:left;'><pre>|   H   |   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>7</td><td style='text-align:left;'><pre>Rz--+---+---+---+---+---@</pre></td></tr><td style='border-right:1px solid red;'>8</td><td style='text-align:left;'><pre>Rz--+---+---+---+---@   |</pre></td></tr><td style='border-right:1px solid red;'>9</td><td style='text-align:left;'><pre>Rz--+---+---+---@   |   |</pre></td></tr><td style='border-right:1px solid red;'>10</td><td style='text-align:left;'><pre>Rz--+---+---@   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>11</td><td style='text-align:left;'><pre>Rz--+---@   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>12</td><td style='text-align:left;'><pre>Rz--@   |   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>13</td><td style='text-align:left;'><pre>|   H   |   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>14</td><td style='text-align:left;'><pre>|   @P--@   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>15</td><td style='text-align:left;'><pre>|   |   H   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>16</td><td style='text-align:left;'><pre>|   @P--+---@   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>17</td><td style='text-align:left;'><pre>|   |   @P--@   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>18</td><td style='text-align:left;'><pre>|   |   |   H   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>19</td><td style='text-align:left;'><pre>|   @P--+---+---@   |   |</pre></td></tr><td style='border-right:1px solid red;'>20</td><td style='text-align:left;'><pre>|   |   @P--+---@   |   |</pre></td></tr><td style='border-right:1px solid red;'>21</td><td style='text-align:left;'><pre>|   |   |   @P--@   |   |</pre></td></tr><td style='border-right:1px solid red;'>22</td><td style='text-align:left;'><pre>|   |   |   |   H   |   |</pre></td></tr><td style='border-right:1px solid red;'>23</td><td style='text-align:left;'><pre>|   @P--+---+---+---@   |</pre></td></tr><td style='border-right:1px solid red;'>24</td><td style='text-align:left;'><pre>|   |   @P--+---+---@   |</pre></td></tr><td style='border-right:1px solid red;'>25</td><td style='text-align:left;'><pre>|   |   |   @P--+---@   |</pre></td></tr><td style='border-right:1px solid red;'>26</td><td style='text-align:left;'><pre>|   |   |   |   @P--@   |</pre></td></tr><td style='border-right:1px solid red;'>27</td><td style='text-align:left;'><pre>|   |   |   |   |   H   |</pre></td></tr><td style='border-right:1px solid red;'>28</td><td style='text-align:left;'><pre>|   @P--+---+---+---+---@</pre></td></tr><td style='border-right:1px solid red;'>29</td><td style='text-align:left;'><pre>|   |   @P--+---+---+---@</pre></td></tr><td style='border-right:1px solid red;'>30</td><td style='text-align:left;'><pre>|   |   |   @P--+---+---@</pre></td></tr><td style='border-right:1px solid red;'>31</td><td style='text-align:left;'><pre>|   |   |   |   @P--+---@</pre></td></tr><td style='border-right:1px solid red;'>32</td><td style='text-align:left;'><pre>|   |   |   |   |   @P--@</pre></td></tr><td style='border-right:1px solid red;'>33</td><td style='text-align:left;'><pre>|   |   |   |   |   |   H</pre></td></tr><td style='border-right:1px solid red;'>34</td><td style='text-align:left;'><pre>|   |   |   |   |   <---></pre></td></tr><td style='border-right:1px solid red;'>35</td><td style='text-align:left;'><pre>|   |   |   |   <---+---></pre></td></tr><td style='border-right:1px solid red;'>36</td><td style='text-align:left;'><pre>|   |   |   |   <--->   |</pre></td></tr><td style='border-right:1px solid red;'>37</td><td style='text-align:left;'><pre>|   |   |   <---+---+---></pre></td></tr><td style='border-right:1px solid red;'>38</td><td style='text-align:left;'><pre>|   |   |   <---+--->   |</pre></td></tr><td style='border-right:1px solid red;'>39</td><td style='text-align:left;'><pre>|   |   |   <--->   |   |</pre></td></tr><td style='border-right:1px solid red;'>40</td><td style='text-align:left;'><pre>|   |   <---+---+---+---></pre></td></tr><td style='border-right:1px solid red;'>41</td><td style='text-align:left;'><pre>|   |   <---+---+--->   |</pre></td></tr><td style='border-right:1px solid red;'>42</td><td style='text-align:left;'><pre>|   |   <---+--->   |   |</pre></td></tr><td style='border-right:1px solid red;'>43</td><td style='text-align:left;'><pre>|   |   <--->   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>44</td><td style='text-align:left;'><pre>|   <---+---+---+---+---></pre></td></tr><td style='border-right:1px solid red;'>45</td><td style='text-align:left;'><pre>|   <---+---+---+--->   |</pre></td></tr><td style='border-right:1px solid red;'>46</td><td style='text-align:left;'><pre>|   <---+---+--->   |   |</pre></td></tr><td style='border-right:1px solid red;'>47</td><td style='text-align:left;'><pre>|   <---+--->   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>48</td><td style='text-align:left;'><pre>|   <--->   |   |   |   |</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*********branch= pure\n",
      "state vector:\n",
      "ZL convention (Zero bit Last in state tuple)\n",
      "(0000100)ZL ( 1.000000 - 0.000000j)\t prob=1.000000\n",
      "total probability of state vector (=one if no measurements)= 1.000000\n",
      "dictionary with key=qubit, value=(Prob(0), Prob(1))\n",
      "{0: (1.0, 0.0),\n",
      " 1: (1.0, 0.0),\n",
      " 2: (0.0, 1.0),\n",
      " 3: (1.0, 0.0),\n",
      " 4: (1.0, 0.0),\n",
      " 5: (1.0, 0.0),\n",
      " 6: (1.0, 0.0)}\n",
      "spike_bit prediction= 2.0\n",
      "-----------------Number of bits= 8\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>|   |   |   |   |   |   |   H</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>|   |   |   |   |   |   H   |</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>|   |   |   |   |   H   |   |</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>|   |   |   |   H   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>|   |   |   H   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>6</td><td style='text-align:left;'><pre>|   |   H   |   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>7</td><td style='text-align:left;'><pre>|   H   |   |   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>8</td><td style='text-align:left;'><pre>Rz--+---+---+---+---+---+---@</pre></td></tr><td style='border-right:1px solid red;'>9</td><td style='text-align:left;'><pre>Rz--+---+---+---+---+---@   |</pre></td></tr><td style='border-right:1px solid red;'>10</td><td style='text-align:left;'><pre>Rz--+---+---+---+---@   |   |</pre></td></tr><td style='border-right:1px solid red;'>11</td><td style='text-align:left;'><pre>Rz--+---+---+---@   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>12</td><td style='text-align:left;'><pre>Rz--+---+---@   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>13</td><td style='text-align:left;'><pre>Rz--+---@   |   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>14</td><td style='text-align:left;'><pre>Rz--@   |   |   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>15</td><td style='text-align:left;'><pre>|   H   |   |   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>16</td><td style='text-align:left;'><pre>|   @P--@   |   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>17</td><td style='text-align:left;'><pre>|   |   H   |   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>18</td><td style='text-align:left;'><pre>|   @P--+---@   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>19</td><td style='text-align:left;'><pre>|   |   @P--@   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>20</td><td style='text-align:left;'><pre>|   |   |   H   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>21</td><td style='text-align:left;'><pre>|   @P--+---+---@   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>22</td><td style='text-align:left;'><pre>|   |   @P--+---@   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>23</td><td style='text-align:left;'><pre>|   |   |   @P--@   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>24</td><td style='text-align:left;'><pre>|   |   |   |   H   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>25</td><td style='text-align:left;'><pre>|   @P--+---+---+---@   |   |</pre></td></tr><td style='border-right:1px solid red;'>26</td><td style='text-align:left;'><pre>|   |   @P--+---+---@   |   |</pre></td></tr><td style='border-right:1px solid red;'>27</td><td style='text-align:left;'><pre>|   |   |   @P--+---@   |   |</pre></td></tr><td style='border-right:1px solid red;'>28</td><td style='text-align:left;'><pre>|   |   |   |   @P--@   |   |</pre></td></tr><td style='border-right:1px solid red;'>29</td><td style='text-align:left;'><pre>|   |   |   |   |   H   |   |</pre></td></tr><td style='border-right:1px solid red;'>30</td><td style='text-align:left;'><pre>|   @P--+---+---+---+---@   |</pre></td></tr><td style='border-right:1px solid red;'>31</td><td style='text-align:left;'><pre>|   |   @P--+---+---+---@   |</pre></td></tr><td style='border-right:1px solid red;'>32</td><td style='text-align:left;'><pre>|   |   |   @P--+---+---@   |</pre></td></tr><td style='border-right:1px solid red;'>33</td><td style='text-align:left;'><pre>|   |   |   |   @P--+---@   |</pre></td></tr><td style='border-right:1px solid red;'>34</td><td style='text-align:left;'><pre>|   |   |   |   |   @P--@   |</pre></td></tr><td style='border-right:1px solid red;'>35</td><td style='text-align:left;'><pre>|   |   |   |   |   |   H   |</pre></td></tr><td style='border-right:1px solid red;'>36</td><td style='text-align:left;'><pre>|   @P--+---+---+---+---+---@</pre></td></tr><td style='border-right:1px solid red;'>37</td><td style='text-align:left;'><pre>|   |   @P--+---+---+---+---@</pre></td></tr><td style='border-right:1px solid red;'>38</td><td style='text-align:left;'><pre>|   |   |   @P--+---+---+---@</pre></td></tr><td style='border-right:1px solid red;'>39</td><td style='text-align:left;'><pre>|   |   |   |   @P--+---+---@</pre></td></tr><td style='border-right:1px solid red;'>40</td><td style='text-align:left;'><pre>|   |   |   |   |   @P--+---@</pre></td></tr><td style='border-right:1px solid red;'>41</td><td style='text-align:left;'><pre>|   |   |   |   |   |   @P--@</pre></td></tr><td style='border-right:1px solid red;'>42</td><td style='text-align:left;'><pre>|   |   |   |   |   |   |   H</pre></td></tr><td style='border-right:1px solid red;'>43</td><td style='text-align:left;'><pre>|   |   |   |   |   |   <---></pre></td></tr><td style='border-right:1px solid red;'>44</td><td style='text-align:left;'><pre>|   |   |   |   |   <---+---></pre></td></tr><td style='border-right:1px solid red;'>45</td><td style='text-align:left;'><pre>|   |   |   |   |   <--->   |</pre></td></tr><td style='border-right:1px solid red;'>46</td><td style='text-align:left;'><pre>|   |   |   |   <---+---+---></pre></td></tr><td style='border-right:1px solid red;'>47</td><td style='text-align:left;'><pre>|   |   |   |   <---+--->   |</pre></td></tr><td style='border-right:1px solid red;'>48</td><td style='text-align:left;'><pre>|   |   |   |   <--->   |   |</pre></td></tr><td style='border-right:1px solid red;'>49</td><td style='text-align:left;'><pre>|   |   |   <---+---+---+---></pre></td></tr><td style='border-right:1px solid red;'>50</td><td style='text-align:left;'><pre>|   |   |   <---+---+--->   |</pre></td></tr><td style='border-right:1px solid red;'>51</td><td style='text-align:left;'><pre>|   |   |   <---+--->   |   |</pre></td></tr><td style='border-right:1px solid red;'>52</td><td style='text-align:left;'><pre>|   |   |   <--->   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>53</td><td style='text-align:left;'><pre>|   |   <---+---+---+---+---></pre></td></tr><td style='border-right:1px solid red;'>54</td><td style='text-align:left;'><pre>|   |   <---+---+---+--->   |</pre></td></tr><td style='border-right:1px solid red;'>55</td><td style='text-align:left;'><pre>|   |   <---+---+--->   |   |</pre></td></tr><td style='border-right:1px solid red;'>56</td><td style='text-align:left;'><pre>|   |   <---+--->   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>57</td><td style='text-align:left;'><pre>|   |   <--->   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>58</td><td style='text-align:left;'><pre>|   <---+---+---+---+---+---></pre></td></tr><td style='border-right:1px solid red;'>59</td><td style='text-align:left;'><pre>|   <---+---+---+---+--->   |</pre></td></tr><td style='border-right:1px solid red;'>60</td><td style='text-align:left;'><pre>|   <---+---+---+--->   |   |</pre></td></tr><td style='border-right:1px solid red;'>61</td><td style='text-align:left;'><pre>|   <---+---+--->   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>62</td><td style='text-align:left;'><pre>|   <---+--->   |   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>63</td><td style='text-align:left;'><pre>|   <--->   |   |   |   |   |</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*********branch= pure\n",
      "state vector:\n",
      "ZL convention (Zero bit Last in state tuple)\n",
      "(00001000)ZL ( 1.000000 - 0.000000j)\t prob=1.000000\n",
      "total probability of state vector (=one if no measurements)= 1.000000\n",
      "dictionary with key=qubit, value=(Prob(0), Prob(1))\n",
      "{0: (1.0, 0.0),\n",
      " 1: (1.0, 0.0),\n",
      " 2: (1.0, 0.0),\n",
      " 3: (0.0, 1.0),\n",
      " 4: (1.0, 0.0),\n",
      " 5: (1.0, 0.0),\n",
      " 6: (1.0, 0.0),\n",
      " 7: (1.0, 0.0)}\n",
      "spike_bit prediction= 3.0\n"
     ]
    }
   ],
   "source": [
    "for num_qbits in range(2, 9):\n",
    "    print('-----------------Number of bits=', num_qbits)\n",
    "    rads = 2*np.pi/16\n",
    "    atom_wr = AtomWriter2(rads=rads, do_write=False)\n",
    "    file_prefix = 'ph_est_nb_b'\n",
    "    emb = CktEmbedder(num_qbits, num_qbits)\n",
    "    wr = PhaseEstSEO_writer(do_write=True,\n",
    "                            num_probe_bits=num_qbits - 1,\n",
    "                            atom_writer=atom_wr,\n",
    "                            file_prefix=file_prefix, \n",
    "                            emb=emb)\n",
    "\n",
    "    wr.close_files()\n",
    "\n",
    "    wr.print_pic_file(jup=True)\n",
    "\n",
    "    init_st_vec = StateVec.get_standard_basis_st_vec([0]*num_qbits)\n",
    "    sim = SEO_simulator(file_prefix, num_qbits, init_st_vec)\n",
    "    StateVec.describe_st_vec_dict(sim.cur_st_vec_dict, \n",
    "            print_st_vec=True, do_pp=True, omit_zero_amps=True, show_pp_probs=True)\n",
    "    \n",
    "    print('spike_bit prediction=', num_qbits - 1 + np.log2(rads/(2*np.pi)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We have printed the result for a range of $num\\_bits$. The very\n",
    "last line for each $num\\_bits$ printed tells the bit where we predict the spike (P(1)>>P(0)) will occur.\n",
    "If \n",
    "\n",
    "$rads = \\frac{2 \\pi}{2^r}$, \n",
    "\n",
    "then we predict that \n",
    "\n",
    "$spike\\_bit + r = num\\_bits -1 = num\\_probes$\n",
    "\n",
    "If $rads$ cannot be expressed in this form, then the distributions over\n",
    "the first $num\\_bits - 1$ bits will have multiple spikes at a bit $spike\\_bit$ such that\n",
    "\n",
    "$rads \\approx 2\\pi \\sum_{spike\\_bit} \\frac{2^{spike\\_bit}}{2^{num\\_probes}}= 2\\pi \\sum_{k=0}^{num\\_probes - 1} \\frac{2^k}{2^{num\\_probes}}n(k)$\n",
    "\n",
    "for $0 \\leq rads \\leq 2\\pi$, where $n(k)=1$ if $k$ is a spike bit\n",
    "and $n(k)=0$ otherwise."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {
    "height": "66px",
    "width": "252px"
   },
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": "block",
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
